#include "G4RunManager.hh"
#include "G4UImanager.hh"
#include "G4VisExecutive.hh"
#include "G4UIExecutive.hh"
#include "QGSP_BERT.hh"
#include "KDM1Globals.hh"
#include "KDM1PhysicsList.hh"
#include "KDM1DetectorConstruction.hh"
#include "KDM1PrimaryGeneratorAction.hh"
#include "KDM1RunAction.hh"
#include "KDM1EventAction.hh"
#include "Randomize.hh"
#include "TFile.h"
#include "TTree.h"
#include <sstream>
#include <istream>
using namespace std;

void PrintUsage();

G4String dataFilePath;
G4String eventInterfaceFilePath;
int kaonCount;
G4String kaonPositionFilePath;
int eventNum;
TTree* tree;
double* energyList;

int main(int argc, char** argv)
{
	dataFilePath = "";
	eventInterfaceFilePath = "";
	kaonCount = 0;
	kaonPositionFilePath = "";
	eventNum = -1;
	bool startUI = false;

	for(int i = 1;i < argc;i++)
	{
		if(argv[i][0] == '-')
		{
			if(argv[i][1] == 'h')
			{
				PrintUsage();
				return 0;
			}
			else if(argv[i][1] == 'c')
			{
				i++;
				kaonCount = atoi(argv[i]);
			}
			else if(argv[i][1] == 'd')
			{
				i++;
				dataFilePath = argv[i];
			}
			else if(argv[i][1] == 'e')
			{
				i++;
				eventInterfaceFilePath = argv[i];
			}
			else if(argv[i][1] == 'p')
			{
				i++;
				kaonPositionFilePath = argv[i];
			}
			else if(argv[i][1] == 'u')
			{
				i++;
				startUI = true;
			}
			else
			{
				PrintUsage();
				return 0;
			}
		}
		else
		{
			PrintUsage();
			return 0;
		}
	}

	bool proceed = true;

	if(kaonCount == 0)
	{
		G4cout << "Must enter a kaon count > 0\n";
		proceed = false;
	}
	if(dataFilePath == "")
	{
		G4cout << "Must provide data file path\n";
		proceed = false;
	}
	if(eventInterfaceFilePath == "")
	{
		G4cout << "Must provide event interface file path\n";
		proceed = false;
	}
	if(kaonPositionFilePath == "")
	{
		G4cout << "Must provide kaon position file path\n";
		proceed = false;
	}

	if(!proceed)
	{
		PrintUsage();
		return 0;
	}

	G4long myseed = 336028;
	CLHEP::HepRandom::setTheSeed(myseed);

	// Make the run manager (runningMan)
	G4RunManager *runningMan = new G4RunManager();
	
	// Instanciate and initialize user initialization classes
	KDM1DetectorConstruction *construction = new KDM1DetectorConstruction();
	runningMan->SetUserInitialization(construction);

	G4VUserPhysicsList *physics = new QGSP_BERT;
	runningMan->SetUserInitialization(physics);

	// Instanciate and initialize visualization manager
	G4VisManager *visMan = new G4VisExecutive();
	visMan->SetVerboseLevel(0);
	visMan->Initialize();

	// Instanciate and initialize user action classes
	KDM1PrimaryGeneratorAction *generator = new KDM1PrimaryGeneratorAction();
	runningMan->SetUserAction(generator);
	
	KDM1RunAction *runAction = new KDM1RunAction();
	runningMan->SetUserAction(runAction);

	KDM1EventAction *eventAction = new KDM1EventAction();
	runningMan->SetUserAction(eventAction);

	// Initialize run manager
	runningMan->Initialize();

	TFile file(dataFilePath,"recreate");

	// Get pointer to UI manager and UI executive, then start session
	G4UImanager *UIman = G4UImanager::GetUIpointer();
	UIman->ApplyCommand("/run/verbose 0");
	UIman->ApplyCommand("/event/verbose 0");
	UIman->ApplyCommand("/tracking/verbose 0");
	if(startUI)
	{
		UIman->ApplyCommand("/vis/scene/create");
		UIman->ApplyCommand("/vis/scene/add/trajectories");
		UIman->ApplyCommand("/vis/open OGLIX");
		for(int i = 0;i < 1;i++)
		{
			UIman->ApplyCommand("/run/beamOn");
		}
		int argcFake = 0;
		G4UIExecutive *ui = new G4UIExecutive(argcFake, argv);
		ui->SessionStart();
		delete ui;
	}
	else
	{
		std::stringstream ss;
		ss << "/run/beamOn " << kaonCount*3;
		UIman->ApplyCommand(ss.str());
	}
	
	delete visMan;
	delete runningMan;

	file.Close();

	return 0;
}

void PrintUsage()
{
	G4cout << "Usage:\n\t-c KaonCount\n\t-d DataFilePath"
		<< "\n\t-e EventInterfaceFilePath\n\t-p KaonPositionFilePath\n\t-u (start UI)\n";
}
